package com.anlu.base.utils;


import com.alibaba.fastjson2.JSON;

import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;

public class ToStringUtil {

    /**
     * 方法描述：对象 toString
     * <p>{@link ToStringUtil#isPrimitive(Class)} -> toString</p>
     * <p>Object = {}</p>
     * <p>CharSequence(isAssignableFrom) -> toString</p>
     * <p>Enum -> toString</p>
     * <p>Array -> toJson</p>
     * <p>Collection -> toJson</p>
     * <p>其他对象 -> 原样返回</p>
     *
     * @param clazz
     * @param obj
     * @return java.lang.Object
     * @author 赵希坤
     * @date 日期：2023/4/4 时间：13:31
     */
    protected static Optional<Object> baseToString(Class<?> clazz, Object obj) {
        if (Object.class.equals(clazz)) {
            return Optional.of("{}");
        }
        //string 基本类型 枚举
        if (CharSequence.class.isAssignableFrom(clazz)
                || clazz.isEnum()
                || isPrimitive(clazz)) {
            return Optional.of(obj.toString());
        }
        //数组 集合
        if (clazz.isArray() || Collection.class.isAssignableFrom(clazz)) {
            return Optional.of(JSON.toJSONString(obj));
        }
        return Optional.of(obj);
    }

    /**
     * 方法描述：对象 toString
     * <p>{@link ToStringUtil#isPrimitive(Class)} -> toString</p>
     * <p>Object -> {}</p>
     * <p>CharSequence(isAssignableFrom) -> toString</p>
     * <p>Enum -> toString</p>
     * <p>Array -> toJson</p>
     * <p>Collection -> toJson</p>
     * <p>其他对象 -> toJson</p>
     *
     * @param obj
     * @return java.lang.Object
     * @author 赵希坤
     * @date 日期：2023/4/4 时间：13:31
     */
    public static Optional<String> toJsonString(Object obj) {
        if (null == obj) {
            return Optional.empty();
        }
        return toJsonString(obj.getClass(), obj);
    }

    /**
     * 方法描述：对象 toString
     * <p>{@link ToStringUtil#isPrimitive(Class)} -> toString</p>
     * <p>Object -> {}</p>
     * <p>CharSequence(isAssignableFrom) -> toString</p>
     * <p>Enum -> toString</p>
     * <p>Array -> toJson</p>
     * <p>Collection -> toJson</p>
     * <p>其他对象 -> toJson</p>
     *
     * @param clazz
     * @param obj
     * @return java.lang.Object
     * @author 赵希坤
     * @date 日期：2023/4/4 时间：13:31
     */
    public static Optional<String> toJsonString(Class<?> clazz, Object obj) {
        if (null == obj) {
            return Optional.empty();
        }
        //string 基本类型 枚举
        if (CharSequence.class.isAssignableFrom(clazz)
                || clazz.isEnum()
                || isPrimitive(clazz)) {
            return Optional.of(obj.toString());
        }
        return Optional.of(JSON.toJSONString(obj));
    }

    /**
     * 方法描述：对象 toString
     * <p>null -> null</p>
     * <p>{@link ToStringUtil#isPrimitive(Class)} -> toString</p>
     * <p>Object -> {}</p>
     * <p>CharSequence(isAssignableFrom) -> toString</p>
     * <p>Enum -> toString</p>
     * <p>Array -> toJson</p>
     * <p>Collection -> toJson</p>
     * <p>Map -> TreeMap，key -> String.valueOf(key) , value -> {@link ToStringUtil#toJsonString(Class, Object)} </p>
     * <p>pojo -> TreeMap，key -> String.valueOf(key) , value -> {@link ToStringUtil#toJsonString(Class, Object)} </p>
     * <p>TreeMap.isEmpty() -> {} </p>
     * <p>TreeMap -> JSON.toJSONString() </p>
     * pojo和map是按照属性自然排序的
     *
     * @param obj
     * @return java.lang.String
     * @author 赵希坤
     * @date 日期：2023/4/4 时间：13:28
     */
    public static Optional<String> toMapString(Object obj) {
        if (null == obj) {
            return Optional.empty();
        }
        Class<?> clazz = obj.getClass();
        //基础类型 和 集合数字
        Optional<Object> o1 = baseToString(clazz, obj);
        if (o1.isPresent() && o1.get() instanceof String) {
            return Optional.of(o1.get().toString());
        }

        TreeMap<String, Object> map = new TreeMap<>();
        //处理map
        if (Map.class.isAssignableFrom(clazz)) {
            ((Map<?, ?>) obj).forEach((k, v) -> {
                if (null != k && null != v) {
                    Optional<String> jsonString = toJsonString(v.getClass(), v);
                    map.put(String.valueOf(k), jsonString.orElse(null));
                }
            });
        } else {
            //处理bo
            BeanReflectUtil.getRWMethod(obj).forEach((k, v) -> {
                Object o = v.get(obj);
                if (null == o) {
                    return;
                }
                Optional<String> jsonString = toJsonString(o.getClass(), o);
                map.put(k, jsonString.orElse(null));
            });
        }
        if (map.isEmpty()) {
            return Optional.of("{}");
        }

        return Optional.of(JSON.toJSONString(map));
    }

    /**
     * 方法描述：是否基本类型
     *
     * @param clazz
     * @return true if and only if this
     * @author 赵希坤
     * @date 日期：2023/4/4 时间：13:24
     * @see Boolean#TYPE
     * @see Character#TYPE
     * @see Byte#TYPE
     * @see Short#TYPE
     * @see Integer#TYPE
     * @see Long#TYPE
     * @see Float#TYPE
     * @see Double#TYPE
     * @see Void#TYPE
     * @see Boolean
     * @see Character
     * @see Byte
     * @see Short
     * @see Integer
     * @see Long
     * @see Float
     * @see Double
     */
    public static boolean isPrimitive(Class<?> clazz) {
        boolean bool = clazz.isPrimitive();
        if (bool) {
            return true;
        }
        switch (clazz.getSimpleName()) {
            case "Boolean":
            case "Character":
            case "Byte":
            case "Short":
            case "Integer":
            case "Long":
            case "Float":
            case "Double":
                return true;
            default:
                return false;
        }
    }
}